
import sys, os

appenginepath = 'C:\\Program Files (x86)\\Google\\google_appengine'
ndbpath = 'C:\\P\\f\\ndb'

sys.path.append(appenginepath)
# sys.path.append(appenginepath+'/lib/yaml/lib')
# sys.path.append(appenginepath+'/lib/webob')
# sys.path.append(appenginepath+'/api')
# sys.path.append(appenginepath+'\\lib')
sys.path.append(appenginepath+'\\lib\\yaml\\lib')
sys.path.append(appenginepath+'\\lib\\webob')
sys.path.append(appenginepath+'\\lib\\fancy_urllib')
sys.path.append(appenginepath+'\\api')

sys.path.append(ndbpath)

import unittest
from google.appengine.api import memcache
from google.appengine.ext import db
from google.appengine.ext import testbed

 
import difflib
import pickle
 
import logging 

from google.appengine.api import memcache
from google.appengine.api import datastore_errors
from google.appengine.api import datastore_types
from google.appengine.api import namespace_manager
from google.appengine.api import users
from google.appengine.datastore import entity_pb
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util

from ndb import model, query, tasklets, test_utils, context 

from google.appengine.datastore import datastore_query
 
import time

def timeit(method):

    def timed(*args, **kw):
        ts = time.time()
        result = method(*args, **kw)
        te = time.time()
 
        print 'Running time = ' + '%2.2f sec' %( te-ts) + '<br />\n'     
        return result

    return timed
        

class Account(model.Model):
  """User account."""

  email = model.StringProperty()
  userid = model.StringProperty()
  nickname = model.StringProperty()

class Message(model.Model):
  """Guestbook message."""

  body = model.TextProperty()
  when = model.FloatProperty()
  userid = model.StringProperty()   

  
class dbAccount(db.Model):
  """User account."""

  email = db.StringProperty()	 
  userid = db.StringProperty()
  nickname = db.StringProperty()

class dbMessage(db.Model):
  """Guestbook message."""

  body = db.TextProperty()
  when = db.FloatProperty()
  userid = db.StringProperty()    
 
 
class INAsyncCase(unittest.TestCase):

  def setUp(self):
    def clear_datastore():
      
      query = Message.query()
      entries =query.fetch(1000)
      print len(entries)
      model.delete_multi(m.key for m in entries)
      
    if ISUNITTEST:
      self.testbed = testbed.Testbed()
      self.testbed.setup_env(app_id=applicationID)
      self.testbed.activate()
      self.testbed.init_datastore_v3_stub()
      self.testbed.init_memcache_stub()
    
    
    clear_datastore(); 
    print '<br />\n'    
    list_Message = []
    
    for i in range(0,AccountNumber):
      newMessage = Message(userid = str(i),body = 's'+ str(i) + STRING_FILLER)
      list_Message.append(newMessage)
      
    model.put_multi(list_Message)
    
    memcache.flush_all()
      

  def tearDown(self):
    if ISUNITTEST:
      self.testbed.deactivate()
  
  @timeit 
  @context.toplevel
  def testFecthAllAsync(self):
    def make_query():
        qry = Message.query().order(-Message.userid)
        options = datastore_query.QueryOptions(batch_size=AccountNumber/2,limit=AccountNumber/2)
        return qry, options
    
    print "="*30 +'<br />\n'
    print "Fetch Half Async" +'<br />\n'
    
    qry, options = make_query()
    pairs = yield qry.map_async(self._hp_callback, options=options)
    for userid, body in pairs:
      print ('user = '+userid+'; Message = '+body[0:4]+'<br />\n')
      
    
  @timeit 
  @context.toplevel
  def testINAsync(self):
    def make_query():
      list_Account =  map(str,range(0,AccountNumber,2))
      print list_Account 
      qry = Message.query(Message.userid.IN(list_Account)).order(-Message.userid)
      # options = datastore_query.QueryOptions(batch_size=10)
      # return qry, options
      return qry
    
    print "="*30 +'<br />\n'
    print "IN Operator Async" +'<br />\n'
    
    qry = make_query()
    messages = qry.fetch(batch_size=5, prefetch_size=5) 
    # pairs = yield qry.map_async(self._hp_callback )
    for m in messages:
      print ('user = '+m.userid+'; Message = '+m.body[0:4]+'<br />\n')
  
    
  @tasklets.tasklet
  def _hp_callback(self, message):
    raise tasklets.Return((message.userid,message.body))


class INCase(unittest.TestCase):

  def setUp(self):
    def clear_datastore():
      
      query = dbMessage.all()
      entries =query.fetch(1000)
      print len(entries)
      db.delete(entries)
    
    if ISUNITTEST:
      self.testbed = testbed.Testbed()
      self.testbed.setup_env(app_id=applicationID)
      self.testbed.activate()
      self.testbed.init_datastore_v3_stub()
      self.testbed.init_memcache_stub()
    
    clear_datastore()
    print '<br />\n'    
    
    list_Message = []
     
    for i in range(0,AccountNumber):
      newMessage = dbMessage(userid = str(i),body = 's'+ str(i) + STRING_FILLER)
      list_Message.append(newMessage)
      
    db.put(list_Message)
      

  def tearDown(self):
    if ISUNITTEST:
      self.testbed.deactivate()
    return False
# And finally, implement the tests.
   
  @timeit 
  def testFecthAll(self):
    print "="*30 +'<br />\n'
    print "Fetch Half" +'<br />\n'
    
    list_Account =  map(str,range(0,AccountNumber))
    qry = db.GqlQuery("SELECT * FROM dbMessage")

    messages = qry.fetch(AccountNumber/2)
    for message in messages:
      print ('user = '+message.userid+'; Message = '+message.body[0:4]+'<br />\n')
    
  @timeit 
  def testIN(self):
    print "="*30 +'<br />\n'
    print "IN Operator" +'<br />\n'
    
    list_Account =  map(str,range(0,AccountNumber,2))
    
    qry = db.GqlQuery("SELECT * FROM dbMessage WHERE userid = :1")
   
    def getMessage(account):
      qry.bind(account)
      messages = qry.fetch(1)
      for message in messages:
        print ('user = '+message.userid+'; Message = '+message.body[0:4]+'<br />\n')
  
    map(getMessage,list_Account)  
  
  @timeit 
  def testIN_SDK_Async(self):
    print "="*30 +'<br />\n'
    print "IN_SDK_Async" +'<br />\n'
    
    list_Account =  map(str,range(0,AccountNumber,2))
    
    qry = db.GqlQuery("SELECT * FROM dbMessage WHERE userid = :1")
    
    results ={}
  
    def getMessage(account):
      qry.bind(account)
      results[account] = qry.run()
 
    map(getMessage,list_Account) 
    
    for account in list_Account:
      for message in results[account]:
        print message.body
    
   
     
      
def testBegin():
  suite = unittest.TestSuite()
  suite.addTest(INCase('testIN'))
  suite.addTest(INCase('testIN_SDK_Async'))
  # suite.addTest(INCase('testFecthAll'))
  suite.addTest(INAsyncCase('testINAsync'))
  # suite.addTest(INAsyncCase('testFecthAllAsync'))
  unittest2.TextTestRunner(verbosity=2).run(suite)
      
class INTest(webapp.RequestHandler):
    def get(self):
      testBegin()
      
    
import optparse
import sys
# Install the Python unittest2 package before you run this script.
import unittest2

USAGE = """%prog SDK_PATH TEST_PATH
Run unit tests for App Engine apps.

SDK_PATH    Path to the SDK installation
TEST_PATH   Path to package containing test modules"""


urls = [('/simpletest.*', INTest)]
app = webapp.WSGIApplication(urls)
   

def main(sdk_path="", test_path=""):
    
    
    if ISUNITTEST:
      sys.path.insert(0, sdk_path)
      import dev_appserver
      dev_appserver.fix_sys_path()
      testBegin()
      
    else:
      util.run_wsgi_app(app)
      
applicationID = 'nihao';
AccountNumber = 100; 
ISUNITTEST = False; 
STRING_FILLER = '+'*1024*0

if __name__ == '__main__':
  
    if ISUNITTEST:
      SDK_PATH = appenginepath;
      TEST_PATH = '/home/hl/ndb/ndb/'
      TEST_PATH = ndbpath + '\\ndb'
      
      main(SDK_PATH, TEST_PATH)   
    else:  
      main()

